package org.joyflow.core.service;

import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.joyflow.core.entity.Db;
import org.joyflow.core.entity.DbConType;
import org.joyflow.core.entity.DbDir;
import org.joyflow.core.entity.DbType;
import org.joyflow.core.entity.MetaTable;
import org.joyflow.core.entity.MetaTableDir;
import org.joyflow.core.entity.MetaTableField;
import org.joyflow.core.instance.DbFactory;
import org.joyflow.core.mapper.DbConTypeMapper;
import org.joyflow.core.mapper.DbDirMapper;
import org.joyflow.core.mapper.DbMapper;
import org.joyflow.core.mapper.DbTypeMapper;
import org.joyflow.core.mapper.MetaTableDirMapper;
import org.joyflow.core.mapper.MetaTableFieldMapper;
import org.joyflow.core.mapper.MetaTableMapper;
import org.joyflow.core.meta.Database;
import org.joyflow.core.meta.DbMeta;
import org.joyflow.core.meta.DbMetaCodes;
import org.joyflow.core.meta.FieldDefinition;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class SpringMetaTableService implements MetaTableServiceInterface {
    private final MetaTableDirMapper metaTableDirMapper;
    private final MetaTableMapper metaTableMapper;
    private final MetaTableFieldMapper metaTableFieldMapper;


    @Override
    public List<MetaTableDir> getDirs() {
        return metaTableDirMapper.selectList(null);
    }

    @Override
    public void insertDir(MetaTableDir dir) {
        metaTableDirMapper.insert(dir);
    }

    @Override
    public void deleteDir(Serializable id) {
        metaTableDirMapper.deleteById(id);
    }

    @Override
    public void renameDir(MetaTableDir dir) {
        metaTableDirMapper.updateById(dir);
    }

    @Override
    public MetaTableDir getDir(Serializable id) {
        return metaTableDirMapper.selectById(id);
    }

    @Override
    public List<MetaTable> getTables() {
        return metaTableMapper.selectList(null);
    }

    @Override
    public List<MetaTable> getTablesByDirId(Serializable dirId) {
        return metaTableMapper.selectList(new QueryWrapper<MetaTable>().eq("dir_id", dirId));
    }

    @Override
    public MetaTable getTableById(Serializable id) {
        return metaTableMapper.selectById(id);
    }

    @Override
    public List<MetaTableField> getFieldsByMetaTableId(Long metaTableId) {
        return metaTableFieldMapper.selectList(new QueryWrapper<MetaTableField>().eq("meta_table_id", metaTableId));
    }

    @Override
    public Object generateDDL(Long metaTableId) {
        MetaTable metaTable = metaTableMapper.selectById(metaTableId);
        Long dbId = metaTable.getDbId();
        SpringDbService dbService = SpringUtil.getBean(SpringDbService.class);
        Db db = dbService.getDb(dbId);
        DbMeta dbMeta = DbMetaCodes.decode(db);
        Database database = new Database(dbMeta);
        List<MetaTableField> fieldsByMetaTableId = getFieldsByMetaTableId(metaTableId);
        List<FieldDefinition> fieldDefinitions = convertToFieldDefinitions(fieldsByMetaTableId);
        return database.getCreateTableStatement(metaTable.getTableName(), fieldDefinitions);
    }

    @Override
    public Object preview(Long metaTableId, int pageIndex, int pageSize) {
        MetaTable metaTable = metaTableMapper.selectById(metaTableId);
        Long dbId = metaTable.getDbId();
        SpringDbService dbService = SpringUtil.getBean(SpringDbService.class);
        Db db = dbService.getDb(dbId);
        DbMeta dbMeta = DbMetaCodes.decode(db);
        Database database = new Database(dbMeta);
         List<MetaTableField> fieldsByMetaTableId = getFieldsByMetaTableId(metaTableId);
        List<FieldDefinition> fieldDefinitions = convertToFieldDefinitions(fieldsByMetaTableId);
        String selectStatement =database.getSelectStatement(metaTable.getTableName(), fieldDefinitions);
        String pageSelectStatement =database.getPageSelectStatement(metaTable.getTableName(), fieldDefinitions, pageIndex, pageSize);
        String countStatement =database.getCountStatement(metaTable.getTableName());
        return null;
    }

    private static List<FieldDefinition> convertToFieldDefinitions(List<MetaTableField> fieldsByMetaTableId) {
        List<FieldDefinition> fieldDefinitions = new ArrayList<>();
        for (MetaTableField field : fieldsByMetaTableId) {
            FieldDefinition fieldDefinition = new FieldDefinition();
            fieldDefinition.setNotNull(field.isNull());
            fieldDefinition.setPrimaryKey(field.isPrimaryKey());
            fieldDefinition.setType(field.getFieldType());
            fieldDefinition.setName(field.getFieldName());
            fieldDefinition.setLength(field.getFieldLength());
            fieldDefinition.setPrecision(field.getFieldPrecision());
            fieldDefinitions.add(fieldDefinition);
        }
        return fieldDefinitions;
    }

}
